// $Id: finder.c 405 2014-03-06 04:33:08Z alan.watson.f $

#define _POSIX_C_SOURCE 200112L

#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/stat.h>
#include <unistd.h>

#include "oaxaca-config.h"
#include "oaxaca.h"
#include "detector.h"
#include "finder.h"
#include "spots.h"

////////////////////////////////////////////////////////////////////////////////

int
oaxaca_finder_initialized(void)
{
  return oaxaca_shm != NULL && oaxaca_shm->finder.initialized;
}

char
oaxaca_finder_command(void)
{
  if (oaxaca_shm == NULL)
    return 0;
  else
    return oaxaca_shm->finder.command;
}

void
oaxaca_finder_set_command(char command)
{
  if (oaxaca_shm != NULL)
    oaxaca_shm->finder.command = command;
}

int 
oaxaca_finder_detector_index(void)
{
  return OAXACA_DETECTOR_INDEX_FINDER;
}

////////////////////////////////////////////////////////////////////////////////

static void
atexitcallee(void)
{
  if (oaxaca_shm != NULL)
    oaxaca_shm->finder.initialized = 0;
  oaxaca_detector_close(oaxaca_finder_detector_index());
}

void
oaxaca_finder_main(void)
{
  int index = oaxaca_finder_detector_index();

  oaxaca_common_main("finder");
  atexit(atexitcallee);
  oaxaca_shm->finder.initialized = 0;
  oaxaca_shm->finder.command     = 'i';
  oaxaca_detector_open(index, OAXACA_FINDER_IDS_CAMERA_ID, 2);    
  oaxaca_shm->finder.initialized = 1;
    
  oaxaca_info("starting command loop.");

  for (;;) {
    int command = oaxaca_shm->finder.command;
    switch (command) {
    case 'i': // start idling
      oaxaca_shm->finder.command = 'I';
      break;
    case 'I': // continue idling
      break;    
    case 'c': // configure
      oaxaca_detector_configure(index);
      oaxaca_shm->finder.command = 'I';
      break;
    case 'd': // loop - dark
      oaxaca_shm->finder.command = 'D';
      oaxaca_detector_dark(index);
      oaxaca_shm->finder.command = 'I';
      break;
    case 'e': // loop - expose
      oaxaca_shm->finder.command = 'E';
      oaxaca_detector_expose(index);
      oaxaca_shm->finder.command = 'I';
      break;
    case 'f': // find spots
      {
        oaxaca_shm->finder.command = 'F';
        int ns = oaxaca_shm->detector[index].ns;
        double s[ns];
        oaxaca_spots_find(NULL, ns, s, oaxaca_shm->detector[index].searchradius, oaxaca_shm->detector[index].refinementradius);
        for (int i = 0; i < ns; ++i)
          oaxaca_shm->detector[index].s[i] = s[i];
        oaxaca_shm->finder.command = 'I';
      }
      break;
    case 'r': // refine spots
      {
        oaxaca_shm->finder.command = 'S';
        int ns = oaxaca_shm->detector[index].ns;
        double r[ns];
        for (int i = 0; i < ns; ++i)
          r[i] = oaxaca_shm->detector[index].r[i];
        double s[ns];
	oaxaca_spots_refine(NULL, ns, r, oaxaca_shm->detector[index].searchradius, oaxaca_shm->detector[index].refinementradius, s);
        for (int i = 0; i < ns; ++i)
          oaxaca_shm->detector[index].s[i] = s[i];
        oaxaca_shm->finder.command = 'I';
      }
      break;
    default:
      oaxaca_error("unrecognized command \'%c\'.", command);
      break;
    }
    oaxaca_usleep(1000);
  }
  
  oaxaca_error("command loop terminated.");
}

////////////////////////////////////////////////////////////////////////////////